<template>
    <div id="tw_table_v2">
        <!-- 表格头部 操作按钮 -->
        <slot name="tableHeader"></slot>
        <div class="table-header pb15 tw_clr" v-if="isTableHeader">
            <div class="table-l">
                <span v-show="multipleSelection.length > 0" class="num tw_cl"
                    style="color: var(--el-text-color-primary);">
                    <el-icon class="mr5 ml15" :size="14" color="var(--el-color-primary)">
                        <WarningFilled />
                    </el-icon>
                    已选择
                    <span class="check-num" style="color: var(--el-color-primary)"> {{ multipleSelection.length }}
                    </span>
                    条记录
                </span>
                <slot name="table-l"></slot>
            </div>
            <div class="table-c">
                <slot name="table-c"></slot>
            </div>
            <div class="table-r tw_cl">
                <slot name="table-r"></slot>

                <div class="tw_cl" v-if="showHeadBtns">
                    <div class="head_btn"
                        v-show="headBtns[i] && (headBtns[i].formatter ? headBtns[i].formatter(headBtns[i], i) : true)"
                        v-for="(item, i) in 2" :key="i">
                        <el-button :type="i == 0 ? 'primary' : ''" v-if="headBtns[i]"
                            @click="headBtns[i]?.click(headBtns[i])">
                            <svg-icon v-if="headBtns[i].icon" :color="i ? '' : '#fff'"
                                :icon-class="headBtns[i]?.icon"></svg-icon>
                            {{ headBtns[i]?.name }}
                        </el-button>
                    </div>

                    <el-dropdown class="ml15" v-if="headBtns.length > 2" placement="bottom">
                        <el-button icon="More">更多</el-button>
                        <template #dropdown>
                            <el-dropdown-menu>
                                <template v-for="(item, index) in headBtns" :key="TwVirtualizedTable">
                                    <el-dropdown-item
                                        v-if="TwVirtualizedTable > 1 && (item.formatter ? item.formatter(item, TwVirtualizedTable) : true)"
                                        @click="item?.click(item)">
                                        <svg-icon v-if="item.icon" :icon-class="item?.icon"></svg-icon>
                                        {{ item?.name }}
                                    </el-dropdown-item>
                                </template>
                            </el-dropdown-menu>
                        </template>
                    </el-dropdown>
                </div>
            </div>
        </div>
        <slot name="tableBotHeader"></slot>
        
        <el-auto-resizer>
            <template #default="{ height, width }">
                <el-table-v2
                    ref="table"
                    :id="id"
                    v-loading="loading"
                    :header-height="49"
                    :row-height="48"
                    :row-class="rowClassName"
                    :columns="columns"
                    :data="dataList"
                    :width="width"
                    v-model:expanded-row-keys="expandedRowKeys"
                    :expand-column-key="expandColumnKey"
                    :height="tableHeight || getH"
                    :fixed="tableFixed"
                    @end-reached="endReached"
                    @scroll="scroll"
                    @row-expand="rowExpand"
                />
            </template>
        </el-auto-resizer>
        
        <!--  分页  -->
        <div class="m-pagination mt10 tw_cr" v-if="showPagination">
            <el-tooltip content="刷新">
                <el-button type="primary" plain link icon="RefreshRight" @click="getTotal" class="mr30" :class="shwoTotalStatusLoading?'animated infinite rotate':''"></el-button>
            </el-tooltip>
            
            <p class="tw_c">总共
                <el-button class="ml10 mr10" type="primary" link @click="getTotal" v-if="!shwoTotalStatus">获取总条数</el-button>
                <el-button class="ml10 mr10" type="primary" link v-else>{{total}}</el-button>
                条记录,每页显示 50 条记录</p>
        </div>
    </div>
</template>

<script setup lang="tsx" name="TwVirtualizedTable">
import { ElAutoResizer, ElCheckbox, TableV2FixedDir, ElTooltip } from 'element-plus'
import  { WarningFilled } from '@element-plus/icons-vue'
import type { FunctionalComponent } from 'vue'
import type { CheckboxValueType, Column } from 'element-plus'

import { commonApi } from "../../api/common";
import { onActivated } from "vue";
import { HeadBtnsItem } from './interface/index'
import SvgIcon from "@/components/SvgIcon/SvgIcon.vue";
import {debounce} from "@/utils";
defineOptions({
    name: 'TwVirtualizedTable'
})
// @ts-ignore
const { proxy } = getCurrentInstance()
// @ts-ignore
const { url, totalUrl, id, method, tableIndex, columns, lists, tableParams, tableHeight, showPagination, botHeight, isCheck, isExpand, showIndex, stripe, border, pageSizesArr, tableBtns, small, headBtns, tableCallback, rowClassName, isTableHeader, isLoadStatus, autoScrollToTop, selectable, layout } = defineProps({
    url: { type: String, default: '' },                                  // 表格请求地址
    totalUrl: { type: String, default: '' },                                  // 表格请求地址
    id: { type: String, default: '' },                                  // 表格id属性，动态计算id
    method: { type: String, default: 'post' },                           // 表格请求类型
    columns: { type: Array, default: () => [] },                          // 表格列渲染数据
    lists: { type: Array, default: () => [] },                        // 表格渲染数据
    tableParams: { type: Object, default: () => { return { pageNumber: 1, pageSize: 25 } } },                     // 表格请求数据
    tableIndex: { type: Number, default: 0 },                            // 单页面多表格的使用场景，用于动态计算表格高度
    tableHeight: { type: Number, default: 0 },                     // 表格固定高度
    showPagination: { type: Boolean, default: true },                    // 分页显示开关
    botHeight: { type: Number, default: 50 },                            // 是分页栏加上边距加底部空白位置高度
    isCheck: { type: Boolean, default: false },                          // checkbox显示开关
    isExpand: { type: Boolean, default: false },                          // checkbox显示开关
    border: { type: Boolean, default: false },                           // 边框线显示开关
    pageSizesArr: { type: Array, default: () => [25, 50, 100] },          // 分页页码
    tableBtns: { type: Object, default: (row) => row || {} },             // 单例按钮渲染数据
    small: { type: Boolean, default: false, },                            // 每页显示条数
    headBtns: { type: Array<HeadBtnsItem>, default: () => [] },                         // 顶部操作按钮
    isTableHeader: { type: Boolean, default: true, },                    // 默认显示表格顶部操作栏
    isLoadStatus: { type: Boolean, default: false, },                    // 默认首次不加载table数据
    highlightCurrentRow: { type: Boolean, default: true, },                 // 是否高亮显示当前选中行
    rowClassName: { type: Function, default: () => {}, },                   // 行样式名称
    selectable: { type: Function, default: () => true, },                     // isCheck必须为true  用于判断选项是否可以点击
    autoScrollToTop: { type: Boolean, default: true, },             // 请求数据后是否自动滚动到顶部
    layout:{ type: String, default: 'total, prev, pager, next, sizes, jumper' },
})

// @ts-ignore
let table = $ref(null)
// @ts-ignore
let getH = $ref(600)
let dataList = $ref([])
let loading = $ref(false)
let total = $ref(0)
let multipleSelection = $ref([])
let showHeadBtns = $ref(true)
let tableFixed = $ref(true)
let loadStatus = $ref(true)
let shwoTotalStatus = $ref(false)
let shwoTotalStatusLoading = $ref(false)
let scrollTop = $ref(0)
const expandColumnKey = 'expandColumnKey'
const expandedRowKeys = ref<string[]>([])

onActivated(() => {
    showHeadBtns = false
    table.scrollToTop(scrollTop+1)
    nextTick(() => {
        showHeadBtns = true
        table.scrollToTop(scrollTop-1)
    })
})

let eimts = defineEmits([ 'checkSelect', 'rowCheck', 'tableCallback', 'rowExpand'])

const scroll = (e) => {
    scrollTop = e.scrollTop
}

const setTableTop = () => {
    table.scrollToTop(0)
}

const setShwoTotalStatus = () => {
    shwoTotalStatus = false
}

const getTotal = () => {
    shwoTotalStatusLoading = true
    commonApi(totalUrl, tableParams, method).then(res => {
        shwoTotalStatus = true
        shwoTotalStatusLoading = false
        total = res
    }).catch(() => {
        shwoTotalStatus = true
        shwoTotalStatusLoading = false
    })
}


const endReached = () => {
    if(loadStatus){
        tableParams.pageNumber++
        getTable()
    }
}

const rowExpand = (obj) => {
    eimts('rowExpand', obj)
}

// 请求表格数据 TODO 这里需要做一个参数校验并给出提示[]
const getTable = () => {
    if (!loading)
        loading = true
    commonApi(url, tableParams, method).then(res => {
        loading = false
        if(res.rows.length==0){
            loadStatus = false
        }
        
        res.rows.forEach(item=>{
            item.checked = false
        })
        
        if(isExpand){
            res.rows.forEach((item, i)=> {
                item['id'] = item.eventId
                item['parentId'] = ''
                item['children'] = [{id: `${item.eventId}_${i}`, parentId: item.eventId}]
            })
        }
        
        if(tableParams.pageNumber == 1){
            dataList = res.rows
            setTableTop()
            loadStatus = true
        }else {
            dataList = [...dataList, ...res.rows]
        }
        // total = res.total
        eimts('tableCallback', dataList, res)
        if(!tableHeight) {
            setTableDataHeight()
        }
    }).catch(() => {
        loading = false
    })
}

type SelectionCellProps = {
    value: boolean
    intermediate?: boolean
    disabled: boolean
    onChange: (value: CheckboxValueType) => void
}

const SelectionCell: FunctionalComponent<SelectionCellProps> = ({value, intermediate = false, disabled = false, onChange,}) => {
    return (
        <ElCheckbox
            onChange={onChange}
            modelValue={value}
            indeterminate={intermediate}
            disabled={disabled}
        />
    )
}

const notNull = (flag) => {
    return flag !== null && flag !== '' && flag !== 'null' && flag !== undefined
}

if (notNull(url)) {
    tableFixed = true
    watch(() => columns, (newValue, oldValue) => {
        if(columns.length>0){
            newValue.forEach(item=>{
                item['key'] = item.prop
                item['dataKey'] = item.prop
                item['title'] = item.label
                if(!item.width){
                    tableFixed = false      // 列包含没有指定width说明有自适应的场景， fixed就必须是false
                    item['flexGrow'] = 1
                }
                
                if(item.formatter){
                    item['cellRenderer'] = ({rowData})=> item.formatter(rowData)
                }else {
                    // item['cellRenderer'] = ({cellData})=> cellData || "-"
                }
            })
            
            if(tableBtns && tableBtns.btns.length>0 && columns[columns.length-1].key != undefined){
                columns.push({
                    key: 'btns',
                    title: tableBtns.label || '操作',
                    width: tableBtns.width || 100,
                    fixed: TableV2FixedDir.RIGHT,
                    cellRenderer: ({ rowData }) => {
                        return ( <p class="tw_cl" style="flex-wrap: nowrap;">
                                {tableBtns.btns.map((item, i)=>{
                                    return (<ElTooltip key={i} effect="dark" placement="top-start" v-slots={{content: scope => (<p>{item.name}</p>)}}>
                                        <el-icon onClick={()=>item.click(rowData)} size="20px" class="pointer mr10">
                                            <SvgIcon icon-class={item.icon} color={item.color}></SvgIcon>
                                        </el-icon>
                                    </ElTooltip>)
                                })}
                        </p>)
                    },
                })
            }
            
            // table 复选开关
            if(isCheck && columns[0].key != 'selection' && columns[0].key != undefined){
                columns.unshift({
                    key: 'selection',
                    width: 50,
                    fixed: TableV2FixedDir.LEFT,
                    cellRenderer: ({ rowData }) => {
                        const onChange = (value: CheckboxValueType) => {
                            rowData.checked = value
                            getAllCheck()
                        }
                        if(!rowData.parentId){
                            return <SelectionCell disabled={!selectable(rowData)} value={rowData.checked} onChange={onChange} />
                        }
                    },
                    
                    headerCellRenderer: () => {
                        const _data = unref(dataList)
                        const onChange = (value: CheckboxValueType) =>{
                            dataList.value = _data.map((row) => {
                                if(selectable(row))
                                row.checked = value
                                return row
                            })
                            getAllCheck()
                        }
                        
                        const allSelected = _data.length == 0?false:_data.every((row) => row.checked)
                        const containsChecked = _data.some((row) => row.checked)
                        
                        return (
                            <SelectionCell
                                value={allSelected}
                                intermediate={containsChecked && !allSelected}
                                onChange={onChange}
                            />
                        )
                    },
                })
            }
            
            if(isExpand && columns[0].key != 'expandColumnKey' && columns[0].key != undefined) {
                columns.unshift({
                    key: 'expandColumnKey',
                    width: 50,
                    fixed: TableV2FixedDir.LEFT,})
            }
        }
    }, { immediate: true })
    if(!isLoadStatus){
        loading = true
        getTable()
    }
} else {
    // 如果是默认传递tabel数据，必须经过数据监听并更新数据
    watch(() => lists, (newValue, oldValue) => {
        dataList = newValue
    }, { immediate: true })
    
}



// @ts-ignore
const setTableDataHeight = debounce(() => {
    let layout = document.getElementById('app')
    if (layout && table) {
        nextTick(() => {
            let dom = document.getElementsByClassName('el-table-v2')[tableIndex || 0]
            if (id) {
                dom = document.getElementById(id)
            }
            if (!dom) {
                setTimeout(() => {
                    setTableDataHeight()
                }, 1000)
                return
            }
            let allXy = getOffsetLeft(dom)
            if(allXy.top == 0) return;  // 等于0等同于找不元素，直接终止
            let layoutH = layout.clientHeight || window.innerHeight
            // if (!showPagination || tableParams.pageSize > total) (layoutH = layoutH + 52)  // 52 是分页栏加上边距高度
            if (!showPagination) (layoutH = layoutH + 52)  // 52 是分页栏加上边距高度
            let height = layoutH - allXy.top - botHeight      // 107 是分页栏加上边距加底部空白位置高度
            if (height < 120) {
                getH = 120
            } else {
                getH = height
            }
        })
    }
})

// 设置表格行数据选择
const toggleRowSelection = (rows, status) => {
    if (isCheck) {
        nextTick(()=>{
            let lists = dataList
            rows.forEach(row => {
                for (let i = 0; i < dataList.length; i++) {
                    if (lists[i][status] == row[status]) {
                        let item = lists[i]
                        table.toggleRowSelection(item)
                    }
                }
            });
        })
        
    } else {
        ElMessage.warning('请打开checkbox相关配置')
    }
}
// 获取table全部list的checkbox
const getAllCheck = () => {
    multipleSelection = dataList.filter((item)=>item.checked)
    return multipleSelection
}
// 设置table全部list的checkbox为true
const setAllCheck = () => {
    table.toggleAllSelection()
}
// 清空用户的选择
const clearSelection = () => {
    table.clearSelection()
}
// 点击当前行
const rowCheck = (item) => {
    eimts('rowCheck', item)
}

const setTableLists = (lists) => {
    dataList = lists
}

const setTableTotal = (num) => {
    total = num
}

const setLoadStatus = () => {
    loadStatus = true
}


const setCurrentRow = (data) => {
    table.setCurrentRow(data)
}
// 递归计算上，左边距值
const getOffsetLeft = (obj) => {
    let tmp = obj.offsetTop
    let lmp = obj.offsetLeft
    let node = obj.offsetParent
    while (node != null) {
        tmp += node.offsetTop
        lmp += node.offsetLeft
        node = node.offsetParent
    }
    return { top: tmp, left: lmp }
}

// @ts-ignore
onMounted(() => {
    if(!tableHeight){
        // setTableDataHeight()
        window.addEventListener('resize', setTableDataHeight)
    }
    
})

// @ts-ignore
onUnmounted(() => {
    if(!tableHeight)
    window.removeEventListener('resize', setTableDataHeight, true)
})

defineExpose({ dataList, setTableDataHeight, toggleRowSelection, getTable, getTotal, setShwoTotalStatus, getAllCheck, setAllCheck, clearSelection, rowCheck, setTableLists, setTableTotal, setLoadStatus, setCurrentRow })

</script>



<style scoped lang="scss">
#tw_table_v2 {
    padding: 20px 20px 0;
    &:focus {outline: none}
    :deep(.el-table-v2) {
        border-radius: 12px;overflow: hidden;
        td.el-table__cell, .el-table__cell.is-leaf { border-bottom: none}
        .el-table-v2__header-cell {background: var(--tw-table-header)}
        .el-table-v2__row {
            color: #606266;
            &:nth-child(even) { background: var(--tw-table-cell);}
            &:hover { background: #ffe6b0 !important;}
            &:active { background: #ffe6b0 !important;}
        }
    }
    .head_btn {margin-left: 15px;}
}
</style>
